// =============================================================
// space test using Coord
// ---------------------------------------
// Author : Woo-Hyun Kim
// Email : woorung@icu.ac.kr or woorung@nhncorp.com
// Date : Oct. 8, 2007
// =============================================================
#include <iostream>

#include <stdlib.h>

#include "Coord.h"

void print_usage(char *prog)
{
	cout << "-------------------------------------------------------------------------" << endl;
	cout << "Usage : " << prog << " [option] [value]" << endl;
	cout << "\t\t-m 1\twrite/read/take test" << endl;
	cout << "\t\t-m 2\ttwo processes' persistent space test with autoclean" << endl;
	cout << "\t\t-m 3\t" << __FILE__ << " will be line-splited and write it to space" << endl;
	cout << "\t\t-m 4\tafter 3, take it from space" << endl;
	cout << endl;
	cout << "-------------------------------------------------------------------------" << endl;
}

int main(int argc, char **argv)
{
	if(argc<2) {
		print_usage(argv[0]);
		exit(-1);
	}

	int opt;
	static char optstr[] = "m";

	int op = 1;

	while((opt=getopt(argc,argv,optstr))!=-1) {
		switch(opt) {
			case 'm' :
				op = atoi(argv[optind++]);
				break;
			default :
				print_usage(argv[0]);
				exit(-1);
		}
	}

	if(op==1) {
		cerr << "##### simple space test #####" << endl;

		Coord space;

		pair<string,string> kv;
		kv.first = "woorung";
		kv.second = "this is first data on key = " + kv.first;
		space.write(kv);
		space.read(kv);
		space.take(kv);
		cerr << kv.second << endl;
	}
	else if(op==2) {
		cerr << "#### space autoclean test using two processes(write/take) ####" << endl;

		pid_t pid = fork();
		if(pid==0) { // child
			cerr << "[child]write data to persistent.space" << endl;

			Coord write_space("persistent.space");
			write_space.autoclean(false);

			pair<string,string> kv;
			kv.first = "woorung";
			kv.second = "this is first data on key = " + kv.first;
			write_space.write(kv);

			cerr << "### after child is killed, persistent.space will be kept until parent process clean it up" << endl;
			exit(1);
		}
		else if(pid>0) { // parent
			cerr << "[parent]take data from persistent.space" << endl;
			
			Coord take_space("persistent.space");
			take_space.autoclean(true);

			pair<string,string> kv;
			kv.first = "woorung";
			take_space.take(kv); // wait until writing data at child
			cerr << "[parent]take ===> " << kv.second << endl;

			waitpid(pid, NULL, 0);

			cerr << "### parent clean up the persistent.space" << endl;
		}
	}
	else if(op==3) {
		Coord xspace("line.space");
		xspace.autoclean(false);

		CLineTokenizer *ltok = new CLineTokenizer();
		ltok->input(__FILE__);
		ltok->filter('\t', '\n', 100);
		vector< vector<string> > token;

		for(int k=0;ltok->getToken(token)>0;) {
			for(int i=0;i<token.size();i++) {
				stringstream ss;
				for(int j=0;j<token[i].size();j++) {
					ss << token[i][j] << '\t';
				}

				pair<string,string> kv;
				char tmp[10];
				sprintf(tmp, "%d", k++);
				kv.first = tmp;
				kv.second = ss.str();
				xspace.write(kv);
				cout << kv.first << ":\t" << kv.second << endl;
			}
			token.clear();
		}
		delete ltok;
	}
	else if(op==4) {
		Coord xspace("line.space");
		xspace.autoclean(false);

		for(int k=0;;k++) {
			pair<string,string> kv;
			char tmp[10];
			sprintf(tmp, "%d", k);
			kv.first = tmp; 
			kv.second = "";

			if(xspace.takeIfExists(kv)<0) {
				break;
			}
			else {
				cout << kv.second << endl;
			}
		}
	}

        return 1;
}
